/*  audioscrobbler.h
 *
 *  Copyright (C) 2008 Guillaume Béland <guillaume.beland@gmail.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
 *
 *  Author : Guillaume Béland <guillaume.beland@gmail.com>
*/ 

#ifndef __AUDIOSCROBBLER_H
#define __AUDIOSCROBBLER_H

#include <glib.h>
#include <time.h>
#include <curl/curl.h>
#include <xmmsclient/xmmsclient.h>

#define VERSION "0.5" /* 0.5DrKosmos */
#define PROTOCOL "1.2" /* Audioscrobbler Protocol version */
#define CLIENT_ID "xmg" /* Client ID, same as xmms2-scrobbler */
#define SCROBBLER_URL "http://post.audioscrobbler.com/" /* Handhsake URL */
#define CONFIG_DIR ".config/xmms2/clients/xmms2-audioscrobbler" /* Config Dir */
#define CONFIG_FILE "config" /* config file */
#define USER_AGENT "xmms2/0.5" 

/**
 * @struct Audioscrobbler struct, contain everything related to audioscrobbler
 * state. queue, url, response and others
 */
typedef struct
{
        guint submit_count;
        char *submit_time;
        
        guint playback_status;

        enum {
                STATUS_OK = 0,
                HANDSHAKING,
                SUBMITING,
                REQUEST_FAILED,
                BAD_PASSWORD,
                HANDSHAKE_FAILED,
                BADTIME,
                BANNED,
                SUBMIT_FAILED,
                BADSESSION,
                QUEUE_TOO_LONG,
                GIVEN_UP,
        } status;

        gchar *status_msg;
        GString *srv_response;
        gint srv_response_size;

        GQueue *queue;
        GQueue *submission;
        gint queue_count;

        guint failures;
        gboolean handshake;
        
        time_t handshake_next;
        time_t submit_next;
        
        gboolean queue_changed;
        
        gchar *session_id;
        gchar *username;
        gchar *password;
        gchar *submit_url;
        gchar *now_playing_url;    

        gboolean debug;
  
} xmms_audioscrobbler_data_t;

/* @struct Simple struct which represent a song. */
typedef struct
{
        gchar *artist;
        gchar *track;
        gchar *album; /* optional */
        guint length; /* in seconds */ /* optional */
        guint tracknumber; /* optional */
        gchar *mbtrackid; /* optional */
        guint started_playing; /*unix time*/
        gchar source; /* P= choosen by user, R= non-personalised broadcast, E= personalised
                         L= Last.fm, U = unknown */
        gchar rating; /* L = LOVE, B= BAN, S = Skip */
        gchar timestamp[33];
            
} xmms_audioscrobbler_song_t;

/* @struct wrapper struct for xmms_audioscrobbler_data_t, xmms_connection_t and the main loop */
typedef struct xmms_client_data_St
{
        xmms_audioscrobbler_data_t *audioscrobbler;
        xmmsc_connection_t *connection;
        GMainLoop *mainloop;

} xmms_client_data_t;

/* Interface declaration */

/**
 * Handle the playback status
 * @param result A xmmsc_result_t representing the result of the playback status
 * @param userdata A void pointer of userdata to pass to the function
 */
void     xmms_audioscrobbler_handle_playback_status (xmmsc_result_t *result, G_GNUC_UNUSED void *userdata); 

/**
 * Set last_duration to the current playtime.
 * @param res xmmsc_result_t representing the result of the playtime request
 * @param userdata A void pointer representing userdata to pass to the function
 */    
void     xmms_audioscrobbler_handle_playtime (xmmsc_result_t *res, G_GNUC_UNUSED void *userdata);

/**
 * Handle the current id broadcast and set the notifier for medialib infor
 * @param result xmmsc_result_t representing the result of the curent id request
 * @param userdata A void pointer representing userdata to pass to the function
 */
void     xmms_audioscrobbler_handle_current_id (xmmsc_result_t *result, G_GNUC_UNUSED void *cdata);

/**
 * Handler function to get the media information from medialib.
 * @param medialib_result A xmmsc_result_t
 * @param userdata A void pointer of data to pass to the function
 */
void     xmms_audioscrobbler_do_mediainfo (xmmsc_result_t *medialib_result, G_GNUC_UNUSED void *userdata) ;

/**
 * Check if the song if submitable and add it to the queue.
 * @param clientdata A xmmsc_client_data_t
 * @param entry A xmms_audioscrobbler_song_t to add to the queue.
 */
void     xmms_audioscrobbler_queue_for_submit (xmms_client_data_t *clientdata, xmms_audioscrobbler_song_t *entry);

/**
 * add a xmms_audioscrobbler_song_t to a GQueue
 * @param audioscrobbler A xmms_audioscrobbler_data_t representing an audioscrobbler object
 * @param entry A xmms_audioscrobbler_song_t representing a song object
 * @returns TRUE if the song was added succesfully 
 */
gboolean xmms_audioscrobbler_add_to_queue (xmms_audioscrobbler_data_t *audioscrobbler,
                                                xmms_audioscrobbler_song_t *entry);

/**
 * Free a xmms_audioscrobbler_song_t 
 * @param song a xmms_audioscrobbler_song_t to be freed
 */
void     xmms_audioscrobbler_song_free (xmms_audioscrobbler_song_t *song);

/**
 * Create, initialize and return a ready to use audioscrobbler object
 * @returns A xmms_audioscrobbler_data_t initialized properly
 */
xmms_audioscrobbler_data_t *     xmms_audioscrobbler_init (void);

/**
 *Get the config directory
 *@return A gchar* containing the config directory
 */
gchar*   xmms_audioscrobbler_get_config_dir (void);

/**
 * Make sure the configuration file exist
 * @param filename The configuration filename
 * @return TRUE if the config file exist
 */
gboolean xmms_audioscrobbler_check_config_file (gchar *filename);

/**
 * Write the configuration to the config file.
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 * @param filename The filename of the configuration file
 * @return TRUE if everything went fine
 */
gboolean xmms_audioscrobbler_write_config (xmms_audioscrobbler_data_t *audioscrobbler, gchar *filename); 

/**
 * Read the configuration to the config file and load the information into the xmms_audioscrobbler_data_t
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 * @param filename The filename of the configuration file
 */
void     xmms_audioscrobbler_read_config (xmms_audioscrobbler_data_t *audioscrobbler, gchar *filename);

/**
 * Decide wheter or not, we should handshake
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 * @returns TRUE if we need to handshake
 */
gboolean xmms_audioscrobbler_should_handshake (xmms_audioscrobbler_data_t *audioscrobbler);

/**
 * Callback function to store response from curl
 * @param ptr A void pointer
 * @param size A size_t
 * @param nmemb A size_t
 * @param userdata A void pointer to pass useful information to the funciton
 * @return a size_t
 */
size_t   xmms_audioscrobbler_store_res (void *ptr, 
                                                size_t size, 
                                                size_t nmemb, 
                                                void *userdata);

/**
 * Build the proper post data for a audioscrobbler handshake with Last.fm
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 * @returns A complete handshake url
 */
gchar*   xmms_audioscrobbler_build_handshake_data (xmms_audioscrobbler_data_t *audioscrobbler);

/**
 * Parse the response of the handshake and store the information properly
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 */
void     xmms_audioscrobbler_parse_handshake (xmms_audioscrobbler_data_t *audioscrobbler); 

/**
 * Build authentification data which consist of md5 (md5 (password) + timestamp)
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 * @returns An md5 encrypted char* representing the authentification data.
 */
gchar*   xmms_audioscrobbler_build_auth_data (xmms_audioscrobbler_data_t *audioscrobbler);

/**
 * Build the post data to submit the submission queue
 * @param curl A CURL pointer
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 * @returns A char* representing the post data
 */
gchar*   xmms_audioscrobbler_build_submit_data (CURL *curl, xmms_audioscrobbler_data_t *audioscrobbler);

/**
 * Submit handshake,now playing or submit data to audioscrobbler protocol,
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 * @param mode a gint for the submiting mode: 0 submit, 1 now playing 2 handshake
 */
void     xmms_audioscrobbler_submit_data (xmms_audioscrobbler_data_t *audioscrobbler, gint mode);

/**
 * Build post data for nowplaying submission
 * @param curl A CURL pointer
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 * @returns A char* containing the post fields for now playing submit
 */
gchar*   xmms_audioscrobbler_build_nowplaying_data (CURL *curl, xmms_audioscrobbler_data_t *audioscrobbler);

/**
 * Parse the submit of NowPlaying and standard submission
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 */
void     xmms_audioscrobbler_parse_submit (xmms_audioscrobbler_data_t *audioscrobbler);

/**
 * Usefull function which HTML espace need string
 * @param curl A CURL pointer
 * @param audioscrobbler A xmms_audioscrobbler_data_t
 * @returns A xmms_audioscrobbler_song_t escaped
 */
xmms_audioscrobbler_song_t*     xmms_audioscrobbler_escape_song (CURL *curl, xmms_audioscrobbler_song_t *song);

#endif
